home *** CD-ROM | disk | FTP | other *** search
- Subject: v08i009: A Micro-Emacs variant that resembles GNU Emacs
- Newsgroups: mod.sources
- Approved: mirror!rs
-
- Submitted by: Bob Larson <seismo!usc-oberon!blarson>
- Mod.sources: Volume 8, Issue 9
- Archive-name: micrognu/Part02
-
-
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create the files:
- # basic.c
- # buffer.c
- # cinfo.c
- # echo.c
- # extend.c
- # file.c
- # match.c
- # This archive created: Sat Nov 15 14:59:46 1986
- export PATH; PATH=/bin:$PATH
- if test -f 'basic.c'
- then
- echo shar: will not over-write existing file "'basic.c'"
- else
- cat << \SHAR_EOF > 'basic.c'
- /*
- * Basic cursor motion commands.
- *
- * The routines in this file are the basic
- * command functions for moving the cursor around on
- * the screen, setting mark, and swapping dot with
- * mark. Only moves between lines, which might make the
- * current buffer framing bad, are hard.
- */
- #include "def.h"
-
- /*
- * Go to beginning of line.
- */
- /*ARGSUSED*/
- gotobol(f, n, k) {
- curwp->w_doto = 0;
- return (TRUE);
- }
-
- /*
- * Move cursor backwards. Do the
- * right thing if the count is less than
- * 0. Error if you try to move back from
- * the beginning of the buffer.
- */
- /*ARGSUSED*/
- backchar(f, n, k) register int n; {
- register LINE *lp;
-
- if (n < 0)
- return (forwchar(f, -n, k));
- while (n--) {
- if (curwp->w_doto == 0) {
- if ((lp=lback(curwp->w_dotp)) == curbp->b_linep) {
- if (k != KRANDOM)
- ewprintf("Beginning of buffer");
- return (FALSE);
- }
- curwp->w_dotp = lp;
- curwp->w_doto = llength(lp);
- curwp->w_flag |= WFMOVE;
- } else
- curwp->w_doto--;
- }
- return (TRUE);
- }
-
- /*
- * Go to end of line.
- */
- /*ARGSUSED*/
- gotoeol(f, n, k) {
- curwp->w_doto = llength(curwp->w_dotp);
- return (TRUE);
- }
-
- /*
- * Move cursor forwards. Do the
- * right thing if the count is less than
- * 0. Error if you try to move forward
- * from the end of the buffer.
- */
- /*ARGSUSED*/
- forwchar(f, n, k) register int n; {
- if (n < 0)
- return (backchar(f, -n, k));
- while (n--) {
- if (curwp->w_doto == llength(curwp->w_dotp)) {
- if (curwp->w_dotp == curbp->b_linep) {
- if (k != KRANDOM)
- ewprintf("End of buffer");
- return (FALSE);
- }
- curwp->w_dotp = lforw(curwp->w_dotp);
- curwp->w_doto = 0;
- curwp->w_flag |= WFMOVE;
- } else
- curwp->w_doto++;
- }
- return (TRUE);
- }
-
- /*
- * Go to the beginning of the
- * buffer. Setting WFHARD is conservative,
- * but almost always the case.
- */
- gotobob(f, n, k) {
- (VOID) setmark(f, n, k) ;
- curwp->w_dotp = lforw(curbp->b_linep);
- curwp->w_doto = 0;
- curwp->w_flag |= WFHARD;
- return (TRUE);
- }
-
- /*
- * Go to the end of the buffer.
- * Setting WFHARD is conservative, but
- * almost always the case.
- */
- gotoeob(f, n, k) {
- (VOID) setmark(f, n, k) ;
- curwp->w_dotp = curbp->b_linep;
- curwp->w_doto = 0;
- curwp->w_flag |= WFHARD;
- return (TRUE);
- }
-
- /*
- * Move forward by full lines.
- * If the number of lines to move is less
- * than zero, call the backward line function to
- * actually do it. The last command controls how
- * the goal column is set.
- */
- /*ARGSUSED*/
- forwline(f, n, k) {
- register LINE *dlp;
-
- if (n < 0)
- return (backline(f, -n, KRANDOM));
- if ((lastflag&CFCPCN) == 0) /* Fix goal. */
- setgoal();
- thisflag |= CFCPCN;
- dlp = curwp->w_dotp;
- while (n-- && dlp!=curbp->b_linep)
- dlp = lforw(dlp);
- curwp->w_dotp = dlp;
- curwp->w_doto = getgoal(dlp);
- curwp->w_flag |= WFMOVE;
- return (TRUE);
- }
-
- /*
- * This function is like "forwline", but
- * goes backwards. The scheme is exactly the same.
- * Check for arguments that are less than zero and
- * call your alternate. Figure out the new line and
- * call "movedot" to perform the motion.
- */
- /*ARGSUSED*/
- backline(f, n, k) {
- register LINE *dlp;
-
- if (n < 0)
- return (forwline(f, -n, KRANDOM));
- if ((lastflag&CFCPCN) == 0) /* Fix goal. */
- setgoal();
- thisflag |= CFCPCN;
- dlp = curwp->w_dotp;
- while (n-- && lback(dlp)!=curbp->b_linep)
- dlp = lback(dlp);
- curwp->w_dotp = dlp;
- curwp->w_doto = getgoal(dlp);
- curwp->w_flag |= WFMOVE;
- return (TRUE);
- }
-
- /*
- * Set the current goal column,
- * which is saved in the external variable "curgoal",
- * to the current cursor column. The column is never off
- * the edge of the screen; it's more like display then
- * show position.
- */
- setgoal() {
-
- curgoal = getcolpos() - 1; /* Get the position. */
- if (curgoal >= ncol) /* Chop to tty width. */
- curgoal = ncol-1;
- }
-
- /*
- * This routine looks at a line (pointed
- * to by the LINE pointer "dlp") and the current
- * vertical motion goal column (set by the "setgoal"
- * routine above) and returns the best offset to use
- * when a vertical motion is made into the line.
- */
- getgoal(dlp) register LINE *dlp; {
- register int c;
- register int col;
- register int newcol;
- register int dbo;
-
- col = 0;
- dbo = 0;
- while (dbo != llength(dlp)) {
- c = lgetc(dlp, dbo);
- newcol = col;
- if (c == '\t')
- newcol |= 0x07;
- else if (ISCTRL(c) != FALSE)
- ++newcol;
- ++newcol;
- if (newcol > curgoal)
- break;
- col = newcol;
- ++dbo;
- }
- return (dbo);
- }
-
- /*
- * Scroll forward by a specified number
- * of lines, or by a full page if no argument.
- * The "2" is the window overlap (this is the default
- * value from ITS EMACS). Because the top line in
- * the window is zapped, we have to do a hard
- * update and get it back.
- */
- /*ARGSUSED*/
- forwpage(f, n, k) register int n; {
- register LINE *lp;
-
- if (f == FALSE) {
- n = curwp->w_ntrows - 2; /* Default scroll. */
- if (n <= 0) /* Forget the overlap */
- n = 1; /* if tiny window. */
- } else if (n < 0)
- return (backpage(f, -n, KRANDOM));
- #ifdef CVMVAS
- else /* Convert from pages */
- n *= curwp->w_ntrows; /* to lines. */
- #endif
- lp = curwp->w_linep;
- while (n-- && lp!=curbp->b_linep)
- lp = lforw(lp);
- curwp->w_linep = lp;
- curwp->w_dotp = lp;
- curwp->w_doto = 0;
- curwp->w_flag |= WFHARD;
- return (TRUE);
- }
-
- /*
- * This command is like "forwpage",
- * but it goes backwards. The "2", like above,
- * is the overlap between the two windows. The
- * value is from the ITS EMACS manual. The
- * hard update is done because the top line in
- * the window is zapped.
- */
- /*ARGSUSED*/
- backpage(f, n, k) register int n; {
- register LINE *lp;
-
- if (f == FALSE) {
- n = curwp->w_ntrows - 2; /* Default scroll. */
- if (n <= 0) /* Don't blow up if the */
- n = 1; /* window is tiny. */
- } else if (n < 0)
- return (forwpage(f, -n, KRANDOM));
- #ifdef CVMVAS
- else /* Convert from pages */
- n *= curwp->w_ntrows; /* to lines. */
- #endif
- lp = curwp->w_linep;
- while (n-- && lback(lp)!=curbp->b_linep)
- lp = lback(lp);
- curwp->w_linep = lp;
- curwp->w_dotp = lp;
- curwp->w_doto = 0;
- curwp->w_flag |= WFHARD;
- return (TRUE);
- }
-
- /*
- * Page the other window. Check to make sure it exists, then
- * nextwind, forwpage and prevwind.
- */
- pagenext(f, n, k) {
- if (wheadp->w_wndp == NULL) {
- ewprintf("No other window");
- return FALSE;
- }
- (VOID) nextwind(f, n, k);
- (VOID) forwpage(f, n, k);
- (VOID) prevwind(f, n, k);
- return TRUE;
- }
-
- /*
- * Set the mark in the current window
- * to the value of dot. A message is written to
- * the echo line unless we are running in a keyboard
- * macro, when it would be silly.
- */
- /*ARGSUSED*/
- setmark(f, n, k) {
- isetmark();
- if (kbdmop == NULL)
- ewprintf("Mark set");
- return (TRUE);
- }
-
- /*
- * Internal set mark routine, used by other functions (daveb).
- */
- isetmark()
- {
- curwp->w_markp = curwp->w_dotp;
- curwp->w_marko = curwp->w_doto;
- }
-
- /*
- * Swap the values of "dot" and "mark" in
- * the current window. This is pretty easy, because
- * all of the hard work gets done by the standard routine
- * that moves the mark about. The only possible
- * error is "no mark".
- */
- /*ARGSUSED*/
- swapmark(f, n, k) {
- register LINE *odotp;
- register int odoto;
-
- if (curwp->w_markp == NULL) {
- ewprintf("No mark in this window");
- return (FALSE);
- }
- odotp = curwp->w_dotp;
- odoto = curwp->w_doto;
- curwp->w_dotp = curwp->w_markp;
- curwp->w_doto = curwp->w_marko;
- curwp->w_markp = odotp;
- curwp->w_marko = odoto;
- curwp->w_flag |= WFMOVE;
- return (TRUE);
- }
-
- /*
- * Go to a specific line, mostly for
- * looking up errors in C programs, which give the
- * error a line number. If an argument is present, then
- * it is the line number, else prompt for a line number
- * to use.
- */
- /*ARGSUSED*/
- gotoline(f, n, k) register int n; {
- register LINE *clp;
- register int s;
- char buf[32];
-
- if (f == FALSE) {
- if ((s=ereply("Goto line: ", buf, sizeof(buf))) != TRUE)
- return (s);
- n = atoi(buf);
- }
-
- clp = lforw(curbp->b_linep); /* "clp" is first line */
- while (n > 1) {
- if (lforw(clp) == curbp->b_linep) break;
- clp = lforw(clp);
- --n;
- }
- curwp->w_dotp = clp;
- curwp->w_doto = 0;
- curwp->w_flag |= WFMOVE;
- return (TRUE);
- }
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'buffer.c'
- then
- echo shar: will not over-write existing file "'buffer.c'"
- else
- cat << \SHAR_EOF > 'buffer.c'
- /*
- * Buffer handling.
- */
- #include "def.h"
-
- /*
- * Attach a buffer to a window. The
- * values of dot and mark come from the buffer
- * if the use count is 0. Otherwise, they come
- * from some other window.
- */
- /*ARGSUSED*/
- usebuffer(f, n, k) {
- register BUFFER *bp;
- register int s;
- char bufn[NBUFN];
-
- /* Get buffer to use from user */
- if (curbp->b_altb != NULL)
- s=eread("Switch to buffer: (default %s) ", bufn, NBUFN,
- EFNEW|EFBUF,
- #ifdef VARARGS
- curbp->b_altb->b_bname
- #else
- &(curbp->b_altb->b_bname), (char *) NULL
- #endif
- ) ;
- else
- s=eread("Switch to buffer: ", bufn, NBUFN, EFNEW|EFBUF
- #ifndef VARARGS
- ,(char *) NULL
- #endif
- );
- if (s == ABORT) return (s);
- if (s == FALSE && curbp->b_altb != NULL) bp = curbp->b_altb ;
- else if ((bp=bfind(bufn, TRUE)) == NULL) return (FALSE);
-
- /* and put it in current window */
- curbp = bp;
- return showbuffer(bp, curwp, WFFORCE|WFHARD);
- }
-
- /*
- * pop to buffer asked for by the user.
- */
- /*ARGSUSED*/
- poptobuffer(f, n, k) {
- register BUFFER *bp;
- register WINDOW *wp;
- register int s;
- char bufn[NBUFN];
-
- /* Get buffer to use from user */
- if (curbp->b_altb != NULL)
- s=eread("Switch to buffer in other window: (default %s) ",
- bufn, NBUFN, EFNEW|EFBUF,
- #ifdef VARARGS
- curbp->b_altb->b_bname
- #else
- &(curbp->b_altb->b_bname) ,(char *) NULL
- #endif
- ) ;
- else
- s=eread("Switch to buffer in other window: ", bufn, NBUFN,
- EFNEW|EFBUF
- #ifndef VARARGS
- , (char *) NULL
- #endif
- ) ;
- if (s == ABORT) return (s);
- if (s == FALSE && curbp->b_altb != NULL) bp = curbp->b_altb ;
- else if ((bp=bfind(bufn, TRUE)) == NULL) return (FALSE);
-
- /* and put it in a new window */
- if ((wp = popbuf(bp)) == NULL) return FALSE;
- curbp = bp;
- curwp = wp;
- return TRUE;
- }
-
- /*
- * Dispose of a buffer, by name.
- * Ask for the name. Look it up (don't get too
- * upset if it isn't there at all!). Clear the buffer (ask
- * if the buffer has been changed). Then free the header
- * line and the buffer header. Bound to "C-X K".
- */
- /*ARGSUSED*/
- killbuffer(f, n, k) {
- register BUFFER *bp;
- register BUFFER *bp1;
- register BUFFER *bp2;
- register WINDOW *wp;
- register int s;
- char bufn[NBUFN];
-
- if ((s=eread("Kill buffer: (default %s) ", bufn, NBUFN, EFNEW|EFBUF,
- #ifdef VARARGS
- curbp->b_bname
- #else
- &(curbp->b_bname)
- #endif
- )) == ABORT) return (s);
- else if (s == FALSE) bp = curbp ;
- else if ((bp=bfind(bufn, FALSE)) == NULL) return FALSE;
-
- if (bp->b_nwnd != 0) {
- if ((bp1 = bp->b_altb) == NULL) return FALSE;
- if (bclear(bp) != TRUE) return TRUE;
- for (wp = wheadp; bp->b_nwnd > 0; wp = wp->w_wndp) {
- /* Special case - could use showbuf, but don't */
- if (wp->w_bufp == bp) {
- --bp->b_nwnd;
- ++bp1->b_nwnd;
- wp->w_bufp = bp1 ;
- wp->w_dotp = bp1->b_dotp;
- wp->w_doto = bp1->b_doto;
- wp->w_markp = bp1->b_markp;
- wp->w_marko = bp1->b_marko;
- wp->w_linep = bp1->b_linep;
- wp->w_flag |= WFMODE|WFFORCE|WFHARD;
- }
- }
- }
- else if (bclear(bp) != TRUE) return TRUE;
- if (bp == curbp) curbp = bp->b_altb;
- free((char *) bp->b_linep); /* Release header line. */
- bp1 = NULL; /* Find the header. */
- bp2 = bheadp;
- while (bp2 != bp) {
- if (bp2->b_altb == bp)
- bp2->b_altb = (bp->b_altb == bp2) ? NULL : bp->b_altb;
- bp1 = bp2;
- bp2 = bp2->b_bufp;
- }
- bp2 = bp2->b_bufp; /* Next one in chain. */
- if (bp1 == NULL) /* Unlink it. */
- bheadp = bp2;
- else
- bp1->b_bufp = bp2;
- while (bp2 != NULL) { /* Finish with altb's */
- if (bp2->b_altb == bp)
- bp2->b_altb = (bp->b_altb == bp2) ? NULL : bp->b_altb;
- bp2 = bp2->b_bufp;
- }
- free(bp->b_bname); /* Release name block */
- free((char *) bp); /* Release buffer block */
- return (TRUE);
- }
-
- /*
- * Save some buffers - just call anycb with the arg flag.
- */
- /*ARGSUSED*/
- savebuffers(f, n, k) {
- if (anycb(f) == ABORT) return ABORT;
- return TRUE;
- }
-
- /*
- * Display the buffer list. This is done
- * in two parts. The "makelist" routine figures out
- * the text, and puts it in a buffer. "popbuf"
- * then pops the data onto the screen. Bound to
- * "C-X C-B".
- */
- /*ARGSUSED*/
- listbuffers(f, n, k) {
- register BUFFER *bp;
- register WINDOW *wp;
- BUFFER *makelist();
- WINDOW *popb();
-
- if ((bp=makelist()) == NULL || (wp=popbuf(bp)) == NULL)
- return FALSE;
- wp->w_dotp = bp->b_dotp; /* fix up if window already on screen */
- wp->w_doto = bp->b_doto;
- return TRUE;
- }
-
- /*
- * This routine rebuilds the text for the
- * list buffers command. Return TRUE if
- * everything works. Return FALSE if there
- * is an error (if there is no memory).
- */
- BUFFER *
- makelist() {
- register char *cp1;
- register char *cp2;
- register int c;
- register BUFFER *bp;
- register LINE *lp;
- register RSIZE nbytes;
- BUFFER *blp;
- char b[6+1];
- char line[128];
-
- if ((blp = bfind("*Buffer List*", TRUE)) == NULL) return NULL;
- if (bclear(blp) != TRUE) return NULL;
- blp->b_flag &= ~BFCHG; /* Blow away old. */
-
- (VOID) strcpy(line, " MR Buffer");
- cp1 = line + 10;
- while(cp1 < line + 4 + NBUFN + 1) *cp1++ = ' ';
- (VOID) strcpy(cp1, "Size File");
- if (addline(blp, line) == FALSE) return NULL;
- (VOID) strcpy(line, " -- ------");
- cp1 = line + 10;
- while(cp1 < line + 4 + NBUFN + 1) *cp1++ = ' ';
- (VOID) strcpy(cp1, "---- ----");
- if (addline(blp, line) == FALSE) return NULL;
- bp = bheadp; /* For all buffers */
- while (bp != NULL) {
- cp1 = &line[0]; /* Start at left edge */
- *cp1++ = (bp == curbp) ? '.' : ' ';
- *cp1++ = ((bp->b_flag&BFCHG) != 0) ? '*' : ' ';
- *cp1++ = ' '; /* Gap. */
- *cp1++ = ' ';
- cp2 = &bp->b_bname[0]; /* Buffer name */
- while ((c = *cp2++) != 0)
- *cp1++ = c;
- while (cp1 < &line[4+NBUFN+1])
- *cp1++ = ' ';
- nbytes = 0; /* Count bytes in buf. */
- if (bp != blp) {
- lp = lforw(bp->b_linep);
- while (lp != bp->b_linep) {
- nbytes += llength(lp)+1;
- lp = lforw(lp);
- }
- }
- (VOID) itor(b, 6, nbytes); /* 6 digit buffer size. */
- cp2 = &b[0];
- while ((c = *cp2++) != 0)
- *cp1++ = c;
- *cp1++ = ' '; /* Gap.. */
- cp2 = &bp->b_fname[0]; /* File name */
- if (*cp2 != 0) {
- while ((c = *cp2++) != 0) {
- if (cp1 < &line[128-1])
- *cp1++ = c;
- }
- }
- *cp1 = 0; /* Add to the buffer. */
- if (addline(blp, line) == FALSE)
- return NULL;
- bp = bp->b_bufp;
- }
- blp->b_dotp = lforw(blp->b_linep); /* put dot at beginning of buffer */
- blp->b_doto = 0;
- return blp; /* All done */
- }
-
- /*
- * Used above.
- */
- static itor(buf, width, num)
- register char buf[]; register int width; register RSIZE num; {
- register RSIZE r;
-
- if (num / 10 == 0) {
- buf[0] = (num % 10) + '0';
- for (r = 1; r < width; buf[r++] = ' ')
- ;
- buf[width] = '\0';
- return 1;
- } else {
- buf[r = itor(buf, width, num / (RSIZE)10)] =
- (num % (RSIZE)10) + '0';
- return r + 1;
- }
- }
-
- /*
- * The argument "text" points to
- * a string. Append this line to the
- * buffer. Handcraft the EOL
- * on the end. Return TRUE if it worked and
- * FALSE if you ran out of room.
- */
- addline(bp, text) register BUFFER *bp; char *text; {
- register LINE *lp;
- register int i;
- register int ntext;
-
- ntext = strlen(text);
- if ((lp=lalloc((RSIZE) ntext)) == NULL)
- return (FALSE);
- for (i=0; i<ntext; ++i)
- lputc(lp, i, text[i]);
- bp->b_linep->l_bp->l_fp = lp; /* Hook onto the end */
- lp->l_bp = bp->b_linep->l_bp;
- bp->b_linep->l_bp = lp;
- lp->l_fp = bp->b_linep;
- if (bp->b_dotp == bp->b_linep) /* If "." is at the end */
- bp->b_dotp = lp; /* move it to new line */
- if (bp->b_markp == bp->b_linep) /* ditto for mark */
- bp->b_markp = lp;
- return (TRUE);
- }
-
- /*
- * Look through the list of buffers, giving the user
- * a chance to save them. Return TRUE if there are
- * any changed buffers afterwards. Buffers that don't
- * have an associated file don't count. Return FALSE
- * if there are no changed buffers.
- */
- anycb(f) {
- register BUFFER *bp;
- register int s = FALSE, save = FALSE;
- char prompt[NFILEN + 11];
-
- for (bp = bheadp; bp != NULL; bp = bp->b_bufp) {
- if (*(bp->b_fname) != '\0'
- && (bp->b_flag&BFCHG) != 0) {
- (VOID) strcpy(prompt, "Save file ");
- (VOID) strcpy(prompt + 10, bp->b_fname);
- if ((f == TRUE || (save = eyorn(prompt)) == TRUE)
- && writeout(bp, bp->b_fname) == TRUE) {
- bp->b_flag &= ~BFCHG;
- upmodes(bp);
- } else s = TRUE;
- if (save == ABORT) return (save);
- save = TRUE;
- }
- }
- if (save == FALSE && kbdmop == NULL)
- ewprintf("(No files need saving)");
- return s;
- }
-
- /*
- * Search for a buffer, by name.
- * If not found, and the "cflag" is TRUE,
- * create a buffer and put it in the list of
- * all buffers. Return pointer to the BUFFER
- * block for the buffer.
- */
- BUFFER *
- bfind(bname, cflag) register char *bname; {
- register BUFFER *bp;
- char *malloc();
- register LINE *lp;
-
- bp = bheadp;
- while (bp != NULL) {
- if (strcmp(bname, bp->b_bname) == 0)
- return (bp);
- bp = bp->b_bufp;
- }
- if (cflag!=TRUE) return NULL;
- /*NOSTRICT*/
- if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL) {
- ewprintf("Can't get %d bytes", sizeof(BUFFER));
- return NULL;
- }
- if ((bp->b_bname=malloc(strlen(bname)+1)) == NULL) {
- ewprintf("Can't get %d bytes", strlen(bname)+1);
- free((char *) bp);
- return NULL;
- }
- if ((lp=lalloc((RSIZE) 0)) == NULL) {
- free(bp->b_bname);
- free((char *) bp);
- return NULL;
- }
- bp->b_altb = bp->b_bufp = NULL;
- bp->b_dotp = lp;
- bp->b_doto = 0;
- bp->b_markp = NULL;
- bp->b_marko = 0;
- bp->b_flag = 0;
- bp->b_nwnd = 0;
- bp->b_linep = lp;
- (VOID) strcpy(bp->b_fname, "");
- (VOID) strcpy(bp->b_bname, bname);
- lp->l_fp = lp;
- lp->l_bp = lp;
- bp->b_bufp = bheadp;
- bheadp = bp;
- return (bp);
- }
-
- /*
- * This routine blows away all of the text
- * in a buffer. If the buffer is marked as changed
- * then we ask if it is ok to blow it away; this is
- * to save the user the grief of losing text. The
- * window chain is nearly always wrong if this gets
- * called; the caller must arrange for the updates
- * that are required. Return TRUE if everything
- * looks good.
- */
- bclear(bp) register BUFFER *bp; {
- register LINE *lp;
- register int s;
-
- if ((bp->b_flag&BFCHG) != 0 /* Changed. */
- && (s=eyesno("Buffer modified; kill anyway")) != TRUE)
- return (s);
- bp->b_flag &= ~BFCHG; /* Not changed */
- while ((lp=lforw(bp->b_linep)) != bp->b_linep)
- lfree(lp);
- bp->b_dotp = bp->b_linep; /* Fix "." */
- bp->b_doto = 0;
- bp->b_markp = NULL; /* Invalidate "mark" */
- bp->b_marko = 0;
- return (TRUE);
- }
-
- /*
- * Display the given buffer in the given window. Flags indicated
- * action on redisplay.
- */
- showbuffer(bp, wp, flags) register BUFFER *bp; register WINDOW *wp; {
- register BUFFER *obp;
- register WINDOW *owp;
-
- if (wp->w_bufp == bp) { /* Easy case! */
- wp->w_flag |= flags;
- return TRUE ;
- }
-
- /* First, dettach the old buffer from the window */
- if ((bp->b_altb = obp = wp->w_bufp) != NULL) {
- if (--obp->b_nwnd == 0) {
- obp->b_dotp = wp->w_dotp;
- obp->b_doto = wp->w_doto;
- obp->b_markp = wp->w_markp;
- obp->b_marko = wp->w_marko;
- }
- }
-
- /* Now, attach the new buffer to the window */
- wp->w_bufp = bp;
-
- if (bp->b_nwnd++ == 0) { /* First use. */
- wp->w_dotp = bp->b_dotp;
- wp->w_doto = bp->b_doto;
- wp->w_markp = bp->b_markp;
- wp->w_marko = bp->b_marko;
- } else
- /* already on screen, steal values from other window */
- for (owp = wheadp; owp != NULL; owp = wp->w_wndp)
- if (wp->w_bufp == bp && owp != wp) {
- wp->w_dotp = owp->w_dotp;
- wp->w_doto = owp->w_doto;
- wp->w_markp = owp->w_markp;
- wp->w_marko = owp->w_marko;
- break;
- }
- wp->w_flag |= WFMODE|flags;
- return TRUE;
- }
-
- /*
- * Pop the buffer we got passed onto the screen.
- * Returns a status.
- */
- WINDOW *
- popbuf(bp) register BUFFER *bp; {
- register WINDOW *wp;
-
- if (bp->b_nwnd == 0) { /* Not on screen yet. */
- if ((wp=wpopup()) == NULL) return NULL;
- } else
- for (wp = wheadp; wp != NULL; wp = wp->w_wndp)
- if (wp->w_bufp == bp) {
- wp->w_flag |= WFHARD|WFFORCE;
- return wp ;
- }
- if (showbuffer(bp, wp, WFHARD) != TRUE) return NULL;
- return wp;
- }
-
- /*
- * Insert another buffer at dot. Very useful.
- */
-
- bufferinsert(f, n, k)
- {
- register BUFFER *bp;
- register LINE *clp;
- register int clo;
- register int nline;
- int s;
- char bufn[NBUFN];
-
- /* Get buffer to use from user */
- if (curbp->b_altb != NULL)
- s=eread("Insert buffer: (default %s) ", bufn, NBUFN,
- EFNEW|EFBUF, &(curbp->b_altb->b_bname),
- (char *) NULL) ;
- else
- s=eread("Insert buffer: ", bufn, NBUFN, EFNEW|EFBUF,
- (char *) NULL) ;
- if (s == ABORT) return (s);
- if (s == FALSE && curbp->b_altb != NULL) bp = curbp->b_altb;
- else if ((bp=bfind(bufn, FALSE)) == NULL) return (FALSE);
-
- if (bp==curbp) {
- ewprintf("Cannot insert buffer into self");
- return (FALSE);
- }
-
- /* insert the buffer */
- nline = 0;
- for (clp = lforw(bp->b_linep); clp != bp->b_linep; clp = lforw(clp)) {
- for (clo = 0; clo < llength(clp); clo++)
- if (linsert((RSIZE)1, lgetc(clp, clo)) == FALSE)
- return (FALSE);
- if (newline(FALSE, 1, KRANDOM) == FALSE) /* fake newline */
- return (FALSE);
- nline++;
- }
- if (kbdmop==NULL) {
- if (nline == 1)
- ewprintf("[Inserted 1 line]");
- else
- ewprintf("[Inserted %d lines]", nline);
- }
-
- clp = curwp->w_linep; /* cosmetic adjustment */
- if (curwp->w_dotp == clp) { /* for offscreen insert */
- while (nline-- && lback(clp)!=curbp->b_linep)
- clp = lback(clp);
- curwp->w_linep = clp; /* adjust framing. */
- curwp->w_flag |= WFHARD;
- }
- return (TRUE);
- }
-
- /*
- * Turn off the dirty bit on this buffer.
- */
- /*ARGSUSED*/
- notmodified(f, n, k)
- {
- register WINDOW *wp;
-
- curbp->b_flag &= ~BFCHG;
- wp = wheadp; /* Update mode lines. */
- while (wp != NULL) {
- if (wp->w_bufp == curbp)
- wp->w_flag |= WFMODE;
- wp = wp->w_wndp;
- }
- ewprintf("Modification-flag cleared");
- return (TRUE);
- }
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'cinfo.c'
- then
- echo shar: will not over-write existing file "'cinfo.c'"
- else
- cat << \SHAR_EOF > 'cinfo.c'
- /*
- * Character class tables.
- * Do it yourself character classification
- * macros, that understand the multinational character set,
- * and let me ask some questions the standard macros (in
- * ctype.h) don't let you ask.
- */
- #include "def.h"
-
- /*
- * This table, indexed by a character drawn
- * from the 256 member character set, is used by my
- * own character type macros to answer questions about the
- * type of a character. It handles the full multinational
- * character set, and lets me ask some questions that the
- * standard "ctype" macros cannot ask.
- */
- char cinfo[256] = {
- _C, _C, _C, _C, /* 0x0X */
- _C, _C, _C, _C,
- _C, _C, _C, _C,
- _C, _C, _C, _C,
- _C, _C, _C, _C, /* 0x1X */
- _C, _C, _C, _C,
- _C, _C, _C, _C,
- _C, _C, _C, _C,
- 0, _P, 0, 0, /* 0x2X */
- _W, _W, 0, _W,
- 0, 0, 0, 0,
- 0, 0, _P, 0,
- _W, _W, _W, _W, /* 0x3X */
- _W, _W, _W, _W,
- _W, _W, 0, 0,
- 0, 0, 0, _P,
- 0, _U|_W, _U|_W, _U|_W, /* 0x4X */
- _U|_W, _U|_W, _U|_W, _U|_W,
- _U|_W, _U|_W, _U|_W, _U|_W,
- _U|_W, _U|_W, _U|_W, _U|_W,
- _U|_W, _U|_W, _U|_W, _U|_W, /* 0x5X */
- _U|_W, _U|_W, _U|_W, _U|_W,
- _U|_W, _U|_W, _U|_W, 0,
- 0, 0, 0, 0,
- 0, _L|_W, _L|_W, _L|_W, /* 0x6X */
- _L|_W, _L|_W, _L|_W, _L|_W,
- _L|_W, _L|_W, _L|_W, _L|_W,
- _L|_W, _L|_W, _L|_W, _L|_W,
- _L|_W, _L|_W, _L|_W, _L|_W, /* 0x7X */
- _L|_W, _L|_W, _L|_W, _L|_W,
- _L|_W, _L|_W, _L|_W, 0,
- 0, 0, 0, _C,
- 0, 0, 0, 0, /* 0x8X */
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0, /* 0x9X */
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0, /* 0xAX */
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0, /* 0xBX */
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- _U|_W, _U|_W, _U|_W, _U|_W, /* 0xCX */
- _U|_W, _U|_W, _U|_W, _U|_W,
- _U|_W, _U|_W, _U|_W, _U|_W,
- _U|_W, _U|_W, _U|_W, _U|_W,
- 0, _U|_W, _U|_W, _U|_W, /* 0xDX */
- _U|_W, _U|_W, _U|_W, _U|_W,
- _U|_W, _U|_W, _U|_W, _U|_W,
- _U|_W, _U|_W, 0, _W,
- _L|_W, _L|_W, _L|_W, _L|_W, /* 0xEX */
- _L|_W, _L|_W, _L|_W, _L|_W,
- _L|_W, _L|_W, _L|_W, _L|_W,
- _L|_W, _L|_W, _L|_W, _L|_W,
- 0, _L|_W, _L|_W, _L|_W, /* 0xFX */
- _L|_W, _L|_W, _L|_W, _L|_W,
- _L|_W, _L|_W, _L|_W, _L|_W,
- _L|_W, _L|_W, 0, 0
- };
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'echo.c'
- then
- echo shar: will not over-write existing file "'echo.c'"
- else
- cat << \SHAR_EOF > 'echo.c'
- /*
- * Echo line reading and writing.
- *
- * Common routines for reading
- * and writing characters in the echo line area
- * of the display screen. Used by the entire
- * known universe.
- */
- #include "def.h"
- #ifdef VARARGS
- # include <varargs.h>
- static veread();
- #endif
- static eformat();
-
- int epresf = FALSE; /* Stuff in echo line flag. */
- /*
- * Erase the echo line.
- */
- eerase() {
- ttcolor(CTEXT);
- ttmove(nrow-1, 0);
- tteeol();
- ttflush();
- epresf = FALSE;
- }
-
- /*
- * Ask "yes" or "no" question.
- * Return ABORT if the user answers the question
- * with the abort ("^G") character. Return FALSE
- * for "no" and TRUE for "yes". No formatting
- * services are available. No newline required.
- */
- eyorn(sp) char *sp; {
- register KEY s;
-
- if (kbdmop == NULL) ewprintf("%s? (y or n) ", sp);
- for (;;) {
- s = getkey(0);
- if (s == 'y' || s == 'Y') return (TRUE);
- if (s == 'n' || s == 'N') return (FALSE);
- if (s == (KCTRL|'G') || s == (KCTLX|KCTRL|'G')
- || s == (KMETA|KCTRL|'G')) {
- (VOID) ctrlg(FALSE, 1, KRANDOM);
- return ABORT;
- }
- if (kbdmop == NULL)
- ewprintf("Please answer y or n. %s? (y or n) ", sp);
- }
- }
-
- /*
- * Like eyorn, but for more important question. User must type either all of
- * "yes" or "no", and the trainling newline.
- */
- eyesno(sp) char *sp; {
- register int s;
- char buf[64];
-
- s = ereply("%s? (yes or no) ", buf, sizeof(buf), sp);
- for (;;) {
- if (s == ABORT) return ABORT;
- if (s != FALSE) {
- if ((buf[0] == 'y' || buf[0] == 'Y')
- && (buf[1] == 'e' || buf[1] == 'E')
- && (buf[2] == 's' || buf[2] == 'S')) return TRUE;
- if ((buf[0] == 'n' || buf[0] == 'N')
- && (buf[1] == 'o' || buf[0] == 'O')) return FALSE;
- }
- s = ereply("Please answer yes or no. %s? (yes or no) ",
- buf, sizeof(buf), sp);
- }
- }
- /*
- * Write out a prompt, and read back a
- * reply. The prompt is now written out with full "ewprintf"
- * formatting, although the arguments are in a rather strange
- * place. This is always a new message, there is no auto
- * completion, and the return is echoed as such.
- */
- #ifdef VARARGS
- ereply(va_alist)
- va_dcl
- {
- register int i;
- va_list pvar;
- register char *fp, *buf;
- register int nbuf;
-
- va_start(pvar);
- fp = va_arg(pvar, char *);
- buf = va_arg(pvar, char *);
- nbuf = va_arg(pvar, int);
- i = veread(fp, buf, nbuf, EFNEW|EFCR, &pvar);
- va_end(pvar);
- return i;
- }
- #else
- /* VARARGS3 */
- ereply(fp, buf, nbuf, arg) char *fp, *buf; int nbuf; long arg; {
- return (eread(fp, buf, nbuf, EFNEW|EFCR, (char *)&arg));
- }
- #endif
-
- /*
- * This is the general "read input from the
- * echo line" routine. The basic idea is that the prompt
- * string "prompt" is written to the echo line, and a one
- * line reply is read back into the supplied "buf" (with
- * maximum length "len"). The "flag" contains EFNEW (a
- * new prompt), an EFFUNC (autocomplete), or EFCR (echo
- * the carriage return as CR).
- */
- /* VARARGS4 */
- #ifdef VARARGS
- eread(va_alist)
- va_dcl
- {
- va_list pvar;
- char *fp, *buf;
- int nbuf, flag, i;
- va_start(pvar);
- fp = va_arg(pvar, char *);
- buf = va_arg(pvar, char *);
- nbuf = va_arg(pvar, int);
- flag = va_arg(pvar, int);
- i = veread(fp, buf, nbuf, flag, &pvar);
- va_end(pvar);
- return i;
- }
- #endif
-
- #ifdef VARARGS
- static veread(fp, buf, nbuf, flag, ap) char *fp; char *buf; va_list *ap; {
- #else
- eread(fp, buf, nbuf, flag, ap) char *fp; char *buf; char *ap; {
- #endif
- register int cpos;
- register int i;
- register KEY c;
-
- cpos = 0;
- if (kbdmop != NULL) { /* In a macro. */
- while ((c = *kbdmop++) != '\0')
- buf[cpos++] = (char) c;
- buf[cpos] = '\0';
- goto done;
- }
- if ((flag&EFNEW)!=0 || ttrow!=nrow-1) {
- ttcolor(CTEXT);
- ttmove(nrow-1, 0);
- epresf = TRUE;
- } else
- eputc(' ');
- eformat(fp, ap);
- tteeol();
- ttflush();
- for (;;) {
- c = getkey(KQUOTE|KNOMAC);
- if ((flag&EFAUTO) != 0 && (c == ' ' || c == CCHR('I'))) {
- cpos += complete(flag, c, buf, cpos);
- continue;
- }
- switch (c) {
- case 0x0D: /* Return, done. */
- if ((flag&EFFUNC) != 0) {
- if ((i = complete(flag, c, buf, cpos)) == 0)
- continue;
- if (i > 0) cpos += i;
- }
- buf[cpos] = '\0';
- if ((flag&EFCR) != 0) {
- ttputc(0x0D);
- ttflush();
- }
- if (kbdmip != NULL) {
- if (kbdmip+cpos+1 > &kbdm[NKBDM-3]) {
- ewprintf("Keyboard macro overflow");
- ttflush();
- return FALSE;
- }
- for (i = 0; i <= cpos; ++i)
- *kbdmip++ = (KEY) buf[i];
- }
- goto done;
-
- case CCHR('G'): /* Bell, abort. */
- eputc(CCHR('G'));
- (VOID) ctrlg(FALSE, 0, KRANDOM);
- ttflush();
- return (ABORT);
-
- case 0x7F: /* Rubout, erase. */
- if (cpos != 0) {
- ttputc('\b');
- ttputc(' ');
- ttputc('\b');
- --ttcol;
- if (ISCTRL(buf[--cpos]) != FALSE) {
- ttputc('\b');
- ttputc(' ');
- ttputc('\b');
- --ttcol;
- }
- ttflush();
- }
- break;
-
- case CCHR('X'): /* C-X */
- case CCHR('U'): /* C-U, kill line. */
- while (cpos != 0) {
- ttputc('\b');
- ttputc(' ');
- ttputc('\b');
- --ttcol;
- if (ISCTRL(buf[--cpos]) != FALSE) {
- ttputc('\b');
- ttputc(' ');
- ttputc('\b');
- --ttcol;
- }
- }
- ttflush();
- break;
-
- case CCHR('Q'): /* C-Q, quote next */
- c = getkey(KQUOTE|KNOMAC) ;
- default: /* All the rest. */
- if (cpos < nbuf-1) {
- buf[cpos++] = (char) c;
- eputc((char) c);
- ttflush();
- }
- }
- }
- done:
- if (buf[0] == '\0')
- return (FALSE);
- return (TRUE);
- }
-
- /*
- * do completion on a list of objects.
- */
- complete(flags, c, buf, cpos) register char *buf; register int cpos; {
- register LIST *lh, *lh2;
- #ifndef MANX
- register /* too many registers mess Manx up */
- #endif
- int i, nxtra;
- int nhits, bxtra;
- int wflag = FALSE;
- int msglen, nshown;
- char *msg;
-
- if ((flags&EFFUNC) != 0) lh = &(symbol[0]->s_list);
- else if ((flags&EFBUF) != 0) lh = &(bheadp->b_list);
- else panic("broken complete call: flags");
-
- if (c == ' ') wflag = TRUE;
- else if (c != '\t' && c != 0x0D) panic("broken complete call: c");
-
- nhits = 0;
- nxtra = HUGE;
-
- while (lh != NULL) {
- for (i=0; i<cpos; ++i) {
- if (buf[i] != lh->l_name[i])
- break;
- }
- if (i == cpos) {
- if (nhits == 0)
- lh2 = lh;
- ++nhits;
- if (lh->l_name[i] == '\0') nxtra = -1;
- else {
- bxtra = getxtra(lh, lh2, cpos, wflag);
- if (bxtra < nxtra) nxtra = bxtra;
- lh2 = lh;
- }
- }
- lh = lh->l_next;
- }
- if (nhits == 0)
- msg = " [No match]";
- else if (nhits > 1 && nxtra == 0)
- msg = " [Ambiguous]";
- else { /* Got a match, do it to it */
- /*
- * Being lazy - ought to check length, but all things
- * autocompleted have known types/lengths.
- */
- if (nxtra < 0 && nhits > 1 && c == ' ') nxtra = 1;
- for (i = 0; i < nxtra; ++i) {
- buf[cpos] = lh2->l_name[cpos];
- eputc(buf[cpos++]);
- }
- ttflush();
- if (nxtra < 0 && c != 0x0D) return 0;
- return nxtra;
- }
- /* Set up backspaces, etc., being mindful of echo line limit */
- msglen = strlen(msg);
- nshown = (ttcol + msglen + 2 > ncol) ?
- ncol - ttcol - 2 : msglen;
- eputs(msg);
- ttcol -= (i = nshown); /* update ttcol! */
- while (i--) /* move back before msg */
- ttputc('\b');
- ttflush(); /* display to user */
- i = nshown;
- while (i--) /* blank out on next flush */
- eputc(' ');
- ttcol -= (i = nshown); /* update ttcol on BS's */
- while (i--)
- ttputc('\b'); /* update ttcol again! */
- return 0;
-
- }
-
- /*
- * The "lp1" and "lp2" point to list structures. The
- * "cpos" is a horizontal position in the name.
- * Return the longest block of characters that can be
- * autocompleted at this point. Sometimes the two
- * symbols are the same, but this is normal.
- */
- getxtra(lp1, lp2, cpos, wflag) register LIST *lp1, *lp2; register int wflag; {
- register int i;
-
- i = cpos;
- for (;;) {
- if (lp1->l_name[i] != lp2->l_name[i]) break;
- if (lp1->l_name[i] == '\0') break;
- ++i;
- if (wflag && !ISWORD(lp1->l_name[i-1])) break;
- }
- return (i - cpos);
- }
-
- /*
- * Special "printf" for the echo line.
- * Each call to "ewprintf" starts a new line in the
- * echo area, and ends with an erase to end of the
- * echo line. The formatting is done by a call
- * to the standard formatting routine.
- */
- #ifdef VARARGS
- ewprintf(va_alist)
- va_dcl
- {
- va_list pvar;
- register char *fp;
-
- va_start(pvar);
- fp = va_arg(pvar, char *);
- #else
- /* VARARGS1 */
- ewprintf(fp, arg) char *fp; {
- #endif
- ttcolor(CTEXT);
- ttmove(nrow-1, 0);
- #ifdef VARARGS
- eformat(fp, &pvar);
- va_end(pvar);
- #else
- eformat(fp, (char *)&arg);
- #endif
- tteeol();
- ttflush();
- epresf = TRUE;
- }
-
- /*
- * Printf style formatting. This is
- * called by both "ewprintf" and "ereply" to provide
- * formatting services to their clients. The move to the
- * start of the echo line, and the erase to the end of
- * the echo line, is done by the caller.
- * Note: %c works, and prints the "name" of the key. However
- * the key must be cast to an int to avoid tripping over
- * various oddities in C argument passing.
- */
- static eformat(fp, ap) register char *fp;
- #ifdef VARARGS
- register va_list *ap;
- #else
- register char *ap;
- #endif
- {
- register int c;
- char kname[NKNAME];
-
- while ((c = *fp++) != '\0') {
- if (c != '%')
- eputc(c);
- else {
- c = *fp++;
- switch (c) {
- case 'c':
- #ifdef VARARGS
- keyname(kname, va_arg(*ap, int));
- #else
- /*NOSTRICT*/
- keyname(kname, *(int *)ap);
- ap += sizeof(int);
- #endif
- eputs(kname);
- break;
-
- case 'd':
- #ifdef VARARGS
- eputi(va_arg(*ap, int), 10);
- #else
- /*NOSTRICT*/
- eputi(*(int *)ap, 10);
- ap += sizeof(int);
- #endif
- break;
-
- case 'o':
- #ifdef VARARGS
- eputi(va_arg(*ap, int), 8);
- #else
- /*NOSTRICT*/
- eputi(*(int *)ap, 8);
- ap += sizeof(int);
- #endif
- break;
-
- case 's':
- #ifdef VARARGS
- eputs(va_arg(*ap, char *));
- #else
- /*NOSTRICT*/
- eputs(*(char **)ap);
- ap += sizeof(char *);
- #endif
- break;
- case 'l':/* explicit longword */
- c = *fp++;
- switch(c) {
- case 'd':
- #ifdef VARARGS
- eputl((long)va_arg(*ap, long), 10L);
- #else
- /*NOSTRICT*/
- eputl(*(long *)ap, 10L);
- ap += sizeof(long);
- #endif
- break;
- default:
- eputc(c);
- break;
- }
- break;
-
- default:
- eputc(c);
- }
- }
- }
- }
-
- /*
- * Put integer, in radix "r".
- */
- static eputi(i, r) register int i; register int r; {
- register int q;
-
- if ((q=i/r) != 0)
- eputi(q, r);
- eputc(i%r+'0');
- }
-
- /*
- * Put long, in radix "r".
- */
- static eputl(l, r) register long l; register long r; {
- register long q;
-
- if ((q=l/r) != 0)
- eputl(q, r);
- eputc((int)(l%r)+'0');
- }
-
- /*
- * Put string.
- */
- eputs(s) register char *s; {
- register int c;
-
- while ((c = *s++) != '\0')
- eputc(c);
- }
-
- /*
- * Put character. Watch for
- * control characters, and for the line
- * getting too long.
- */
- static eputc(c) register char c; {
- if (ttcol+2 < ncol) {
- if (ISCTRL(c) != FALSE) {
- eputc('^');
- c ^= 0x40;
- }
- ttputc(c);
- ++ttcol;
- }
- }
-
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'extend.c'
- then
- echo shar: will not over-write existing file "'extend.c'"
- else
- cat << \SHAR_EOF > 'extend.c'
- /*
- * Extended (M-X) commands.
- */
- #include "def.h"
-
- /*
- * This function modifies the keyboard
- * binding table, by adjusting the entries in the
- * big "bindings" array. Most of the grief deals with the
- * prompting for additional arguments.
- */
- /*ARGSUSED*/
- bindtokey(f, n, k) {
- register int s;
- register SYMBOL *sp;
- int c;
- char xname[NXNAME];
-
- if (kbdmop == NULL)
- ewprintf("Set key globally: ") ;
- c = (int) getkey(0);
- if ((s=eread("Set key %c to command: ", xname, NXNAME, EFNEW|EFFUNC,
- #ifdef VARARGS
- c
- #else
- (char *) &c, (char *) NULL
- #endif
- )) != TRUE)
- return (s);
- if ((sp=symlookup(xname)) == NULL) {
- ewprintf("[No match]");
- return (FALSE);
- }
- binding[(KEY) c] = sp; /* rebind new. */
- return (TRUE);
- }
-
- /*
- * User function to unbind keys. Just call the unbind we already have.
- */
- /*ARGSUSED*/
- unsetkey(f, n, k) {
- register KEY key;
-
- if (kbdmop == NULL) ewprintf("Unset key globally: ") ;
- key = getkey(0);
- if (key == (KCTRL|'G') || key == (KCTLX|KCTRL|'G')
- || key == (KMETA|KCTRL|'G')) {
- (VOID) ctrlg(FALSE, 1, KRANDOM);
- return ABORT;
- }
- binding[key] = NULL;
- return TRUE;
- }
-
- /*
- * Extended command. Call the message line
- * routine to read in the command name and apply autocompletion
- * to it. When it comes back, look the name up in the symbol table
- * and run the command if it is found and has the right type.
- * Print an error if there is anything wrong.
- */
- /*ARGSUSED*/
- extend(f, n, k) {
- register SYMBOL *sp;
- register int s;
- char xname[NXNAME];
-
- if (f == FALSE)
- s = eread("M-x ", xname, NXNAME, EFNEW|EFFUNC
- #ifndef VARARGS
- , (char *) NULL
- #endif
- ) ;
- else
- s = eread("%d M-x ", xname, NXNAME, EFNEW|EFFUNC,
- #ifdef VARARGS
- n
- #else
- (char *) &n, (char *) NULL
- #endif
- ) ;
- if (s != TRUE) return (s);
- if ((sp=symlookup(xname)) != NULL)
- return ((*sp->s_funcp)(f, n, KRANDOM));
- ewprintf("[No match]");
- return FALSE;
- }
-
- /*
- * Read a key from the keyboard, and look it
- * up in the binding table. Display the name of the function
- * currently bound to the key. Say that the key is not bound
- * if it is indeed not bound, or if the type is not a
- * "builtin". This is a bit of overkill, because this is the
- * only kind of function there is.
- */
- /*ARGSUSED*/
- desckey(f, n, k) {
- register SYMBOL *sp;
- register KEY c;
-
- if (kbdmop == NULL) ewprintf("Describe key briefly: ");
- c = getkey(0);
- if (kbdmop != NULL) return TRUE;
- if ((sp=binding[c]) == NULL)
- ewprintf("%c is undefined", (int) c);
- else
- ewprintf("%c runs the command %s", (int) c, sp->s_name);
- return (TRUE);
- }
-
- /*
- * This function creates a table, listing all
- * of the command keys and their current bindings, and stores
- * the table in the standard pop-op buffer (the one used by the
- * directory list command, the buffer list command, etc.). This
- * lets MicroEMACS produce it's own wall chart. The bindings to
- * "ins-self" are only displayed if there is an argument.
- */
- /*ARGSUSED*/
- wallchart(f, n, k) {
- register int key;
- register SYMBOL *sp;
- register char *cp1;
- register char *cp2;
- BUFFER *bp;
- char buf[64];
-
- bp = bfind("*Help*", TRUE);
- if (bclear(bp) != TRUE) /* Clear it out. */
- return TRUE;
- for (key=0; key<NKEYS; ++key) { /* For all keys. */
- sp = binding[key];
- if (sp != NULL
- && (f!=FALSE
- || strcmp(sp->s_name, "self-insert-command")!=0)) {
- keyname(buf, key);
- cp1 = &buf[0]; /* Find end. */
- while (*cp1 != 0)
- ++cp1;
- while (cp1 < &buf[32]) /* Goto column 32. */
- *cp1++ = ' ';
- cp2 = sp->s_name; /* Add function name. */
- while (*cp1++ = *cp2++)
- ;
- if (addline(bp, buf) == FALSE)
- return (FALSE);
- }
- }
- return popbuf(bp) == NULL ? FALSE : TRUE;
- }
-
- #ifdef STARTUP
- /*
- * Define the commands needed to do startup-file processing.
- * This code is mostly a kludge just so we can get startup-file processing.
- *
- * If you're serious about having this code, you should rewrite it.
- * To wit:
- * It has lots of funny things in it to make the startup-file look
- * like a GNU startup file; mostly dealing with parens and semicolons.
- * This should all vanish.
- *
- * It uses the same buffer as keyboard macros. The fix is easy (make
- * a new function "execmacro" that takes a pointer to char and
- * does what ctlxe does on it. Make ctlxe and excline both call it.)
- * but would slow down the non-micro version.
- *
- * We define eval-expression because it's easy. It's pretty useless,
- * since it duplicates the functionality of execute-extended-command.
- * All of this is just to support startup files, and should be turned
- * off for micros.
- */
-
- /*
- * evalexpr - get one line from the user, and run it. Identical in function
- * to extend, but easy.
- */
- /*ARGSUSED*/
- evalexpr(f, n, k) {
- register int s;
- char exbuf[NKBDM];
-
- if ((s = ereply("Eval: ", exbuf, NKBDM)) != TRUE)
- return s;
- return excline(exbuf);
- }
- /*
- * evalbuffer - evaluate the current buffer as line commands. Useful
- * for testing startup files.
- */
- /*ARGSUSED*/
- evalbuffer(f, n, k) {
- register LINE *lp;
- register BUFFER *bp = curbp;
- register int s;
- static char excbuf[NKBDM];
- char *strncpy();
-
- for (lp = lforw(bp->b_linep); lp != bp->b_linep; lp = lforw(lp)) {
- if (llength(lp) >= NKBDM + 1) return FALSE ;
- (VOID) strncpy(excbuf, ltext(lp), NKBDM);
- if ((s = excline(excbuf)) != TRUE) return s;
- }
- return TRUE;
- }
- /*
- * evalfile - go get a file and evaluate it as line commands. You can
- * go get your own startup file if need be.
- */
- /*ARGSUSED*/
- evalfile(f, n, k) {
- register int s;
- char fname[NFILEN];
-
- if ((s = ereply("Load file: ", fname, NFILEN)) != TRUE)
- return s;
- return load(fname);
- }
-
- /*
- * load - go load the file name we got passed.
- */
- load(fname) char *fname; {
- register int s;
- char excbuf[NKBDM];
-
- if (ffropen(fname) == FIOERR)
- return FALSE;
- while ((s = ffgetline(excbuf, NKBDM)) == FIOSUC)
- if (excline(excbuf) != TRUE) break;
- (VOID) ffclose();
- return s == FIOEOF;
- }
-
- /*
- * excline - run a line from a load file or eval-expression.
- */
- excline(line) register char *line; {
- register char *funcp, *argp = NULL;
- char *skipwhite(), *parsetoken(), *backquote();
- int status;
-
- /* Don't know if it works; don't care - mwm */
- if (kbdmip != NULL || kbdmop != NULL) {
- ewprintf("Not now!") ;
- return FALSE;
- }
-
- funcp = skipwhite(line);
- if (*funcp == '\0') return TRUE; /* No error on blank lines */
- line = parsetoken(funcp);
- if (*line != '\0') {
- *line++ = '\0';
- line = skipwhite(line);
- if ((*line >= '0' && *line <= '9') || *line == '-') {
- argp = line;
- line = parsetoken(line);
- }
- }
-
- kbdmip = &kbdm[0];
- if (argp != NULL) {
- *kbdmip++ = (KEY) (KCTRL|'U');
- *kbdmip++ = (KEY) atoi(argp);
- }
- *kbdmip++ = (KEY) (KMETA|'X');
- /* Pack in function */
- while (*funcp != '\0')
- if (kbdmip+1 <= &kbdm[NKBDM-3]) *kbdmip++ = (KEY) *funcp++;
- else {
- ewprintf("eval-expression macro overflow");
- ttflush();
- return FALSE;
- }
- *kbdmip++ = '\0'; /* done with function */
- /* Pack away all the args now... */
- while (*line != '\0') {
- argp = skipwhite(line);
- if (*argp == '\0') break ;
- line = parsetoken(argp) ;
- /* Slightly bogus for strings. But they should be SHORT! */
- if (kbdmip+(line-argp)+1 > &kbdm[NKBDM-3]) {
- ewprintf("eval-expression macro overflow");
- ttflush();
- return FALSE;
- }
- if (*line != '\0') *line++ = '\0';
- if (*argp != '"') {
- if (*argp == '\'') ++argp;
- while (*argp != '\0')
- *kbdmip++ = (KEY) *argp++;
- *kbdmip++ = '\0';
- }
- else { /* Quoted strings special again */
- ++argp;
- while (*argp != '"' && *argp != '\0')
- if (*argp != '\\') *kbdmip++ = (KEY) *argp++;
- else argp = backquote(++argp, TRUE);
- /* Quotes strings are gotkey'ed, so no trailing null */
- }
- }
- *kbdmip++ = (KEY) (KCTLX|')');
- *kbdmip++ = '\0';
- kbdmip = NULL;
- status = ctlxe(FALSE, 1, KRANDOM);
- kbdm[0] = (KCTLX|')');
- return status;
- }
- /*
- * a pair of utility functions for the above
- */
- char *
- skipwhite(s) register char *s; {
-
- while ((*s == ' ' || *s == '\t' || *s == ')' || *s == '(')
- && *s != '\0')
- if (*s == ';') *s = '\0' ;
- else s++;
- return s;
- }
-
- char *
- parsetoken(s) register char *s; {
-
- if (*s != '"')
- while (*s != ' ' && *s != '\t' && *s != '(' && *s != ')'
- && *s != '\0') {
- if (*s == ';') *s = '\0';
- else s++;
- }
- else /* Strings get special treatment */
- do {
- /* Beware: You can \ out the end of the string! */
- if (*s == '\\') ++s;
- if (ISLOWER(*s)) *s = TOUPPER(*s);
- } while (*++s != '"' && *s != '\0');
- return s;
- }
- /*
- * Put a backquoted string element into the keyboard macro. Return pointer
- * to char following backquoted stuff.
- */
- char *
- backquote(in, flag) char *in; {
- switch (*in++) {
- case 'T': *kbdmip++ = (KEY) (KCTRL|'I');
- break;
- case 'N': *kbdmip++ = (KEY) (KCTRL|'J');
- break;
- case 'R': *kbdmip++ = (KEY) (KCTRL|'M');
- break;
- case '^': *kbdmip = (KEY) (KCTRL|*in++);
- if (flag != FALSE && *kbdmip == (KEY) (KCTRL|'X')) {
- if (*in == '\\') in = backquote(++in, FALSE);
- else *kbdmip++ = (KEY) *in++;
- kbdmip[-1] |= (KEY) KCTLX;
- } else ++kbdmip;
- break;
- case 'E':
- if (flag != TRUE) *kbdmip++ = (KEY) (KCTRL|'[');
- else if (*in != '\\') *kbdmip++ = (KEY) (KMETA|*in++);
- else {
- in = backquote(++in, FALSE);
- kbdmip[-1] |= (KEY) KMETA;
- }
- break;
- }
- return in;
- }
- #endif STARTUP
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'file.c'
- then
- echo shar: will not over-write existing file "'file.c'"
- else
- cat << \SHAR_EOF > 'file.c'
- /*
- * File commands.
- */
- #include "def.h"
-
- BUFFER *findbuffer();
-
- /*
- * insert a file into the current buffer. Real easy - just call the
- * insertfile routine with the file name.
- */
- /*ARGSUSED*/
- fileinsert(f, n, k) {
- register int s;
- char fname[NFILEN];
-
- if ((s=ereply("Insert file: ", fname, NFILEN)) != TRUE)
- return (s);
- adjustcase(fname);
- return (insertfile(fname, (char *) NULL)); /* don't set buffer name */
- }
-
- /*
- * Select a file for editing.
- * Look around to see if you can find the
- * fine in another buffer; if you can find it
- * just switch to the buffer. If you cannot find
- * the file, create a new buffer, read in the
- * text, and switch to the new buffer.
- */
- /*ARGSUSED*/
- filevisit(f, n, k) {
- register BUFFER *bp;
- int s;
- char fname[NFILEN];
-
- if ((s=ereply("Find file: ", fname, NFILEN)) != TRUE)
- return (s);
- if ((bp = findbuffer(fname, &s)) == NULL) return s;
- curbp = bp;
- if (showbuffer(bp, curwp, WFHARD) != TRUE) return FALSE;
- if (bp->b_fname[0] == 0)
- return (readin(fname)); /* Read it in. */
- return TRUE;
- }
-
- /*
- * Pop to a file in the other window. Same as last function, just
- * popbuf instead of showbuffer.
- */
- /*ARGSUSED*/
- poptofile(f, n, k) {
- register BUFFER *bp;
- register WINDOW *wp;
- int s;
- char fname[NFILEN];
-
- if ((s=ereply("Find file in other window: ", fname, NFILEN)) != TRUE)
- return (s);
- if ((bp = findbuffer(fname, &s)) == NULL) return s;
- if ((wp = popbuf(bp)) == NULL) return FALSE;
- curbp = bp;
- curwp = wp;
- if (bp->b_fname[0] == 0)
- return (readin(fname)); /* Read it in. */
- return TRUE;
- }
-
- /*
- * given a file name, either find the buffer it uses, or create a new
- * empty buffer to put it in.
- */
- BUFFER *
- findbuffer(fname, s) char *fname; int *s; {
- register BUFFER *bp;
- char bname[NBUFN];
-
- adjustcase(fname);
- for (bp=bheadp; bp!=NULL; bp=bp->b_bufp) {
- if (strcmp(bp->b_fname, fname) == 0) {
- return bp;
- }
- }
- makename(bname, fname); /* New buffer name. */
- while ((bp=bfind(bname, FALSE)) != NULL) {
- *s = ereply("Buffer name: ", bname, NBUFN);
- if (*s == ABORT) /* ^G to just quit */
- return NULL;
- if (*s == FALSE) { /* CR to clobber it */
- bp->b_fname[0] = '\0';
- break;
- }
- }
- if (bp == NULL) bp = bfind(bname, TRUE);
- *s = FALSE;
- return bp;
- }
-
- /*
- * Read the file "fname" into the current buffer.
- * Make all of the text in the buffer go away, after checking
- * for unsaved changes. This is called by the "read" command, the
- * "visit" command, and the mainline (for "uemacs file").
- */
- readin(fname) char *fname; {
- register int status;
- register WINDOW *wp;
-
- if (bclear(curbp) != TRUE) /* Might be old. */
- return TRUE;
- status = insertfile(fname, fname) ;
- curbp->b_flag &= ~BFCHG; /* No change. */
- for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) {
- if (wp->w_bufp == curbp) {
- wp->w_linep = lforw(curbp->b_linep);
- wp->w_dotp = lforw(curbp->b_linep);
- wp->w_doto = 0;
- wp->w_markp = NULL;
- wp->w_marko = 0;
- }
- }
- return status;
- }
- /*
- * insert a file in the current buffer, after dot. Set mark
- * at the end of the text inserted, point at the beginning.
- * Return a standard status. Print a summary (lines read,
- * error message) out as well. If the
- * BACKUP conditional is set, then this routine also does the read
- * end of backup processing. The BFBAK flag, if set in a buffer,
- * says that a backup should be taken. It is set when a file is
- * read in, but not on a new file (you don't need to make a backup
- * copy of nothing).
- *
- * Warning: Adds a trainling nl to files that don't end in one!
- * Need to fix, but later (I suspect that it will require a change
- * in the fileio files for all systems involved).
- */
- insertfile(fname, newname) char fname[], newname[]; {
- register LINE *lp1;
- register LINE *lp2;
- LINE *olp; /* Line we started at */
- int opos; /* and offset into it */
- register WINDOW *wp;
- register int i;
- register int nbytes;
- int s, nline;
- BUFFER *bp;
- char line[NLINE];
-
- bp = curbp; /* Cheap. */
- if (newname != (char *) NULL)
- (VOID) strcpy(bp->b_fname, newname);
- if ((s=ffropen(fname)) == FIOERR) /* Hard file open. */
- goto out;
- if (s == FIOFNF) { /* File not found. */
- if (kbdmop == NULL)
- if (newname != NULL)
- ewprintf("(New file)");
- else ewprintf("(File not found)");
- goto out;
- }
- opos = curwp->w_doto;
- /* Open a new line, at point, and start inserting after it */
- (VOID) lnewline();
- olp = lback(curwp->w_dotp);
- nline = 0; /* Don't count fake line at end */
- while ((s=ffgetline(line, NLINE)) == FIOSUC) {
- nbytes = strlen(line);
- if ((lp1=lalloc((RSIZE) nbytes)) == NULL) {
- s = FIOERR; /* Keep message on the */
- break; /* display. */
- }
- lp2 = lback(curwp->w_dotp);
- lp2->l_fp = lp1;
- lp1->l_fp = curwp->w_dotp;
- lp1->l_bp = lp2;
- curwp->w_dotp->l_bp = lp1;
- for (i=0; i<nbytes; ++i)
- lputc(lp1, i, line[i]);
- ++nline;
- }
- (VOID) ffclose(); /* Ignore errors. */
- if (s==FIOEOF && kbdmop==NULL) { /* Don't zap an error. */
- if (nline == 1)
- ewprintf("(Read 1 line)");
- else
- ewprintf("(Read %d lines)", nline);
- }
- /* Set mark at the end of the text */
- curwp->w_markp = curwp->w_dotp;
- curwp->w_marko = curwp->w_doto;
- /* Now, delete the results of the lnewline we started with */
- curwp->w_dotp = olp;
- curwp->w_doto = opos;
- (VOID) ldelnewline();
- curwp->w_doto = opos; /* and dot is right */
- #ifdef BACKUP
- if (newname != NULL)
- bp->b_flag |= BFCHG | BFBAK; /* Need a backup. */
- else bp->b_flag |= BFCHG;
- #else
- bp->b_flag |= BFCHG;
- #endif
- /* if the insert was at the end of buffer, set lp1 to the end of
- * buffer line, and lp2 to the beginning of the newly inserted
- * text. (Otherwise lp2 is set to NULL.) This is
- * used below to set pointers in other windows correctly if they
- * are also at the end of buffer.
- */
- lp1 = bp->b_linep;
- if (curwp->w_markp == lp1)
- lp2 = curwp->w_dotp;
- else {
- out: lp2 = NULL;
- }
- for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) {
- if (wp->w_bufp == curbp) {
- wp->w_flag |= WFMODE|WFEDIT;
- if (wp != curwp && lp2 != NULL) {
- if (wp->w_dotp == lp1)
- wp->w_dotp = lp2;
- if (wp->w_markp == lp1)
- wp->w_markp = lp2;
- if (wp->w_linep == lp1)
- wp->w_linep = lp2;
- }
- }
- }
- if (s == FIOERR) /* False if error. */
- return (FALSE);
- return (TRUE);
- }
-
- /*
- * Take a file name, and from it
- * fabricate a buffer name. This routine knows
- * about the syntax of file names on the target system.
- * BDC1 left scan delimiter.
- * BDC2 optional second left scan delimiter.
- * BDC3 optional right scan delimiter.
- */
- makename(bname, fname) char bname[]; char fname[]; {
- register char *cp1;
- register char *cp2;
-
- cp1 = &fname[0];
- while (*cp1 != 0)
- ++cp1;
- #ifdef BDC2
- while (cp1!=&fname[0] && cp1[-1]!=BDC1 && cp1[-1]!=BDC2)
- --cp1;
- #else
- while (cp1!=&fname[0] && cp1[-1]!=BDC1)
- --cp1;
- #endif
- cp2 = &bname[0];
- #ifdef BDC3
- while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=BDC3)
- *cp2++ = *cp1++;
- #else
- while (cp2!=&bname[NBUFN-1] && *cp1!=0)
- *cp2++ = *cp1++;
- #endif
- *cp2 = 0;
- }
-
- /*
- * Ask for a file name, and write the
- * contents of the current buffer to that file.
- * Update the remembered file name and clear the
- * buffer changed flag. This handling of file names
- * is different from the earlier versions, and
- * is more compatable with Gosling EMACS than
- * with ITS EMACS.
- */
- /*ARGSUSED*/
- filewrite(f, n, k) {
- register int s;
- char fname[NFILEN];
-
- if ((s=ereply("Write file: ", fname, NFILEN)) != TRUE)
- return (s);
- adjustcase(fname);
- if ((s=writeout(curbp, fname)) == TRUE) {
- (VOID) strcpy(curbp->b_fname, fname);
- #ifdef BACKUP
- curbp->b_flag &= ~(BFBAK | BFCHG);
- #else
- curbp->b_flag &= ~BFCHG;
- #endif
- upmodes(curbp);
- }
- return (s);
- }
-
- /*
- * Save the contents of the current buffer back into
- * its associated file. Do nothing if there have been no changes
- * (is this a bug, or a feature). Error if there is no remembered
- * file name. If this is the first write since the read or visit,
- * then a backup copy of the file is made.
- */
- /*ARGSUSED*/
- filesave(f, n, k) {
- register int s;
-
- if ((curbp->b_flag&BFCHG) == 0) { /* Return, no changes. */
- if (kbdmop == NULL) ewprintf("(No changes need to be saved)");
- return (TRUE);
- }
- if (curbp->b_fname[0] == 0) { /* Must have a name. */
- ewprintf("No file name");
- return (FALSE);
- }
- #ifdef BACKUP
- if ((curbp->b_flag&BFBAK) != 0) {
- s = fbackupfile(curbp->b_fname);
- if (s == ABORT) /* Hard error. */
- return FALSE;
- if (s == FALSE /* Softer error. */
- && (s=eyesno("Backup error, save anyway")) != TRUE)
- return (s);
- }
- #endif
- if ((s=writeout(curbp, curbp->b_fname)) == TRUE) {
- #ifdef BACKUP
- curbp->b_flag &= ~(BFCHG | BFBAK);
- #else
- curbp->b_flag &= ~BFCHG;
- #endif
- upmodes(curbp);
- }
- return (s);
- }
-
- /*
- * This function performs the details of file
- * writing; writing the file in buffer bp to
- * file fn. Uses the file management routines
- * in the "fileio.c" package. Most of the grief
- * is checking of some sort.
- */
- writeout(bp, fn) register BUFFER *bp; char *fn; {
- register int s;
- register LINE *lp;
-
- if ((s=ffwopen(fn)) != FIOSUC) /* Open writes message. */
- return (FALSE);
- lp = lforw(bp->b_linep); /* First line. */
- while (lp != bp->b_linep) {
- if ((s=ffputline(&(ltext(lp))[0], llength(lp))) != FIOSUC)
- break;
- lp = lforw(lp);
- }
- if (s == FIOSUC) { /* No write error. */
- s = ffclose();
- if (s==FIOSUC && kbdmop==NULL)
- ewprintf("Wrote %s", fn);
- } else /* Ignore close error */
- (VOID) ffclose(); /* if a write error. */
- if (s != FIOSUC) /* Some sort of error. */
- return (FALSE);
- return (TRUE);
- }
-
- /*
- * Tag all windows for bp (all windows if bp NULL) as needing their
- * mode line updated.
- */
- upmodes(bp) register BUFFER *bp; {
- register WINDOW *wp;
-
- for (wp = wheadp; wp != NULL; wp = wp->w_wndp)
- if (bp == NULL || curwp->w_bufp == bp) wp->w_flag |= WFMODE;
- }
-
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'match.c'
- then
- echo shar: will not over-write existing file "'match.c'"
- else
- cat << \SHAR_EOF > 'match.c'
- /*
- * Name: MicroEMACS
- * Limited parenthesis matching routines
- * Version: Gnu30
- * Last edit: 13-Jul-86
- * Created: 19-May-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic
- *
- * The hacks in this file implement automatic matching
- * of (), [], {}, and other characters. It would be
- * better to have a full-blown syntax table, but there's
- * enough overhead in the editor as it is.
- *
- * Since I often edit Scribe code, I've made it possible to
- * blink arbitrary characters -- just bind delimiter characters
- * to "blink-matching-paren-hack"
- */
- #include "def.h"
-
- /* Balance table. When balance() encounters a character
- * that is to be matched, it first searches this table
- * for a balancing left-side character. If the character
- * is not in the table, the character is balanced by itself.
- * This is to allow delimiters in Scribe documents to be matched.
- */
-
- static struct balance {
- char left, right;
- } bal[] = {
- { '(', ')' },
- { '[', ']' },
- { '{', '}' },
- { '<', '>' },
- { '\0','\0'}
- };
-
- /*
- * Fake the GNU "blink-matching-paren" variable.
- * If the argument exists, nonzero means show,
- * zero means don't. If it doesn't exist,
- * pretend it's nonzero.
- */
-
- blinkparen(f, n, k)
- {
- register char *command;
- register SYMBOL *sp;
-
- if (f == FALSE)
- n = 1;
- command = (n == 0) ? "self-insert-command" :
- "blink-matching-paren-hack";
- if ((sp=symlookup(command)) == NULL) {
- ewprintf("blinkparen: no binding for %s",command);
- return (FALSE);
- }
- binding[(KEY) ')'] = sp; /* rebind paren */
- return (TRUE);
- }
-
- /*
- * Self-insert character, then show matching character,
- * if any. Bound to "blink-matching-paren-command".
- */
-
- showmatch(f, n, k)
- {
- register int i, s;
-
- if (k == KRANDOM)
- return(FALSE);
- for (i = 0; i < n; i++) {
- if ((s = selfinsert(f, 1, k)) != TRUE)
- return(s);
- if (balance(k) != TRUE) /* unbalanced -- warn user */
- ttbeep();
- }
- return (TRUE);
- }
-
- /*
- * Search for and display a matching character.
- *
- * This routine does the real work of searching backward
- * for a balancing character. If such a balancing character
- * is found, it uses displaymatch() to display the match.
- */
-
- static balance(k)
- int k;
- {
- register LINE *clp;
- register int cbo;
- int c;
- int i;
- int rbal, lbal;
- int depth;
-
- rbal = k & KCHAR;
- if ((k&KCTRL)!=0 && rbal>='@' && rbal<='_') /* ASCII-ify. */
- rbal -= '@';
-
- /* See if there is a matching character -- default to the same */
-
- lbal = rbal;
- for (i = 0; bal[i].right != '\0'; i++)
- if (bal[i].right == rbal) {
- lbal = bal[i].left;
- break;
- }
-
- /* Move behind the inserted character. We are always guaranteed */
- /* that there is at least one character on the line, since one was */
- /* just self-inserted by blinkparen. */
-
- clp = curwp->w_dotp;
- cbo = curwp->w_doto - 1;
-
- depth = 0; /* init nesting depth */
-
- for (;;) {
- if (cbo == 0) { /* beginning of line */
- clp = lback(clp);
- if (clp == curbp->b_linep)
- return (FALSE);
- cbo = llength(clp)+1;
- }
- if (--cbo == llength(clp)) /* end of line */
- c = '\n';
- else
- c = lgetc(clp,cbo); /* somewhere in middle */
-
- /* Check for a matching character. If still in a nested */
- /* level, pop out of it and continue search. This check */
- /* is done before the nesting check so single-character */
- /* matches will work too. */
- if (c == lbal) {
- if (depth == 0) {
- displaymatch(clp,cbo);
- return (TRUE);
- }
- else
- depth--;
- }
- /* Check for another level of nesting. */
- if (c == rbal)
- depth++;
- }
- }
-
-
- /*
- * Display matching character.
- * Matching characters that are not in the current window
- * are displayed in the echo line. If in the current
- * window, move dot to the matching character,
- * sit there a while, then move back.
- */
-
- static displaymatch(clp, cbo)
- register LINE *clp;
- register int cbo;
- {
- register LINE *tlp;
- register int tbo;
- register int cp;
- register int bufo;
- register int c;
- int inwindow;
- char buf[NLINE];
-
- /* Figure out if matching char is in current window by */
- /* searching from the top of the window to dot. */
-
- inwindow = FALSE;
- for (tlp = curwp->w_linep; tlp != lforw(curwp->w_dotp); tlp = lforw(tlp))
- if (tlp == clp)
- inwindow = TRUE;
-
- if (inwindow == TRUE) {
- tlp = curwp->w_dotp; /* save current position */
- tbo = curwp->w_doto;
-
- curwp->w_dotp = clp; /* move to new position */
- curwp->w_doto = cbo;
- curwp->w_flag |= WFMOVE;
-
- update(); /* show match */
- sleep(1); /* wait a bit */
-
- curwp->w_dotp = tlp; /* return to old position */
- curwp->w_doto = tbo;
- curwp->w_flag |= WFMOVE;
- update();
- }
- else { /* match not in this window so display line in echo area */
- bufo = 0;
- for (cp = 0; cp < llength(clp); cp++) { /* expand tabs */
- c = lgetc(clp,cp);
- if (c != '\t')
- buf[bufo++] = c;
- else
- do {
- buf[bufo++] = ' ';
- } while (bufo & 7);
- }
- buf[bufo++] = '\0';
- ewprintf("Matches %s",buf);
- }
- return (TRUE);
- }
- SHAR_EOF
- fi # end of overwriting check
- # End of shell archive
- exit 0
-
-